# --针对行间调度式收获路径方式的总路径长度计算
import math
import pandas as pd
import numpy as np


class LineSchedule():
    def __init__(self, length_field=float(), width_field=float(), turn_raduis=6, harvest_width=3):
        self.length_field = length_field
        self.width_field = width_field
        self.turn_raduis = turn_raduis
        self.harvest_width = harvest_width
        self.num_points = self.num_points()

# 首先进行分行操作--确定田块行号最大的行
    def segment_line(self):
        if self.length_field >= self.width_field:
            if self.width_field % self.harvest_width != 0:
                self.max_point = math.ceil(self.width_field / self.harvest_width)
            else:
                self.max_point = self.width_field / self.harvest_width
        else:
            if self.length_field % self.harvest_width != 0:
                self.max_point = math.ceil(self.length_field / self.harvest_width)
            else:
                self.max_point = self.length_field / self.harvest_width
        return self.max_point

# 生成田块的完整行号
    def num_points(self):
        self.num_line_points = list(range(0, self.segment_line()))
        return self.num_line_points

# 计算转弯操作的最佳间隔行数
    def suitable_line(self):
        suit_line = (2 * self.turn_raduis) / self.harvest_width
        return suit_line

# 使用pd矩阵计算距离
    def caculation_distance(self):
        distance_pd = pd.DataFrame(data=range(0, len(self.num_points)), columns=['num_points'])
        pd.set_option('display.max_columns', None)
        pd.set_option('display.max_rows', None)  # 数据全行全列显示
        pd.set_option('expand_frame_repr', False)
        for i in self.num_points:
            distance_pd[str(i)] = distance_pd.apply(lambda x: self.get_result_method(x.num_points, i), axis=1)
        distance_pd_static = distance_pd.drop(columns=['num_points'])
        self.first_choice(data=distance_pd_static)

    def first_choice(self, data=None):
        data = data.replace(0, np.inf)
        data_one = data
        min_sum_one = 0
        i = 0
        j = 0
        i_list_one = []
        while j < len(data.columns):
            i_list_one.append(i)
            try:
                min_my = data_one[str(i)].idxmin()
                min_values = data_one[str(i)].min()
                if min_values == np.inf:
                    min_values = 0
                else:
                    min_sum_one += min_values
            except:
                min_my = data_one[i].idxmin()
            data_one = data_one.drop(i, axis=0)
            i = min_my
            j = j + 1
        print('向较小行号选择的结果：' + str(i_list_one))
        min_sum_one = round(min_sum_one, 2)
        self.min_sum_one = min_sum_one
        print('转弯路径总长度为：' + str(min_sum_one))

        data_two = data
        min_sum_two = 0
        m = 0
        k = 0
        i_list_two = []
        while k < len(data.columns):
            i_list_two.append(m)
            try:
                min_my_two = data_two[str(m)].sort_index(ascending=False).idxmin()
                min_values_two = data_two[str(m)].min()
                if min_values_two == np.inf:
                    min_values_two = 0
                else:
                    min_sum_two += min_values_two
            except:
                min_my_two = data_two[m].idxmin()
            data_two = data_two.drop(m, axis=0)
            m = min_my_two
            k = k + 1
        print('向较大行号选择的结果：' + str(i_list_two))
        min_sum_two = round(min_sum_two, 2)
        self.min_sum_two = min_sum_two
        print('转弯路径总长度为：' + str(min_sum_two))

# 某一行与其他行的转弯距离计算
    def get_result_method(self, num_point=None, num_i=None):
        x = abs(num_point - num_i)
        L = 0
        if x < self.suitable_line():
            try:
                L = (2 * self.turn_raduis) * (math.pi - 2 * (math.atan(
                    x * self.harvest_width / ((4 * self.turn_raduis ** 2 - x ** 2 * self.harvest_width ** 2) ** 0.5))))
            except:
                L = 0
        elif x == self.suitable_line():
            L = math.pi * self.turn_raduis
        elif x > self.suitable_line():
            L = math.pi * self.turn_raduis + (x - self.suitable_line()) * self.harvest_width
        elif x == 0:
            L = 0
        return round(L, 1)

# 计算完整收获过程的行驶路径总长
    def all_distance(self):
        num_radius = len(self.num_line_points) - 1
        if self.length_field > self.width_field:
            line_length = self.length_field
        else:
            line_length = self.width_field
        straight_length = num_radius * line_length
        all_distance = self.min_sum_one + straight_length
        return all_distance


example_field = LineSchedule(83, 46, 6, 3)
example_field.caculation_distance()
print('完成收获的总路径长度为：' + str(example_field.all_distance()))